# 序列化：pickling
# 把变量从内存中变成可存储或传输的过程称之为序列化
# 序列化之后，就可以把序列化后的内容写入磁盘，或者通过网络传输到别的机器上。反过来，把变量内容从序列化的对象重新读到内存里称之为反序列化，即unpickling。
# Python提供了pickle模块来实现序列化。

# 尝试把一个对象序列化并写入文件：
import pickle
d = dict(name='Daniel', age=20, score=100)
print(pickle.dumps(d))
# pickle.dumps()方法把任意对象序列化成一个bytes，然后，就可以把这个bytes写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object：
f = open('D:\\HWork\\PythonFile\\day5\\w_test.txt', 'wb')
pickle.dump(d, f)
f.close()
# 当我们要把对象从磁盘读到内存时，可以先把内容读到一个bytes，然后用pickle.loads()方法反序列化出对象，也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象：
f = open('D:\\HWork\\PythonFile\\day5\\w_test.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)  # 这个变量和原来的变量是完全不相干的对象，它们只是内容相同而已。

# JSON： JSON表示的对象就是标准的JavaScript语言的对象
import json
d=dict(name="Daniel",age=15,score=90)
data = json.dumps(d)
print('JSON Data is a str:',data)
# dumps()方法返回一个str，内容就是标准的JSON。类似的，dump()方法可以直接把JSON写入一个file-like Object

#要把JSON反序列化为Python对象，用loads()或者对应的load()方法，前者把JSON的字符串反序列化，后者从file-like Object中读取字符串并反序列化：
json_str='{"age":18,"score":60,"name":"Joker"}'
print(json.loads(json_str))

#JSON进阶
#Python的dict对象可以直接序列化为JSON的{}，不过，很多时候，我们更喜欢用class表示对象，比如定义Student类，然后序列化：

"""https://docs.python.org/3/library/json.html#json.dumps
错误写法：import json
class Student(object):
    def __init__(self,name,age,score):
        self.name=name
        self.age=age
        self.score=score
s=Student('Jack',20,89)
print(json.dumps(s))
"""
import json
class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
    def __str__(self):
        return 'Student object (%s,%s,%s)'% (self.name,self.age,self.score)

s = Student('Jack', 20, 89)
std_data=json.dumps(s,default=lambda obj: obj.__dict__)
print('Dump Student:',std_data)
rebuild = json.loads(std_data,object_hook=lambda d: Student(d['name'],d['age'],d['score']))
print(rebuild)

#Python语言特定的序列化模块是pickle，但如果要把序列化搞得更通用、更符合Web标准，就可以使用json模块。